import logging
from django.views.generic import TemplateView
from common.merchant import merchant_db
from common.merchant import role_db
from common.permission import handler as permission_handler
from common.merchant import handler as merchant_handler
from common.merchant.models import RoleLevel
from django.utils.decorators import method_decorator
from common.utils.decorator import response_wrapper, validate_form, check_user_vcode
from common.utils.api import token_required
from django.forms.models import model_to_dict
from django.views.decorators.http import require_GET
from .merchant_form import MerchantListForm, MerchantCreateForm, RoleCreateForm, RoleListForm
from common.utils.maestro_exceptions import (
    MaestroException,
    ACCESS_DENIED
)

_LOGGER = logging.getLogger(__name__)


class MerchantView(TemplateView):
    @method_decorator(token_required)
    @method_decorator(validate_form(MerchantListForm))
    def get(self, req, cleaned_data):
        page, size = cleaned_data['page'], cleaned_data['size']
        paginator_dct = dict(page=page, size=size)
        items, total_count = merchant_db.list_merchant(paginator_dct)
        resp_items = []
        for data in items:
            data['updated_at'], data['created_at'] = str(data['updated_at']), str(data['created_at'])
            resp_items.append(data)
        return dict(list=resp_items, page=paginator_dct.get('page', 1), size=len(resp_items), total_count=total_count)

    @method_decorator(token_required)
    @method_decorator(validate_form(MerchantCreateForm))
    def post(self, req, cleaned_data):
        user_id = req.user_id
        user_role_level = merchant_handler.get_user_roles_information(user_id)
        if not user_role_level['root']:
            raise MaestroException(ACCESS_DENIED, '非超级用户权限不足')
        merchant_name = cleaned_data['merchant_name']
        desc = cleaned_data['desc']
        merchant_db.create_merchant(merchant_name, desc)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(MerchantView, self).dispatch(*args, **kwargs)


class SingleMerchantView(TemplateView):
    @method_decorator(token_required)
    def get(self, req, merchant_name):
        merchant = merchant_db.get_merchant(dict(merchant_name=merchant_name))
        return model_to_dict(merchant) if merchant else {}

    @method_decorator(token_required)
    @method_decorator(validate_form(MerchantCreateForm))
    def put(self, req, merchant_id, cleaned_data):
        merchant_id = int(merchant_id)
        user_id = req.user_id
        user_role_level = merchant_handler.get_user_roles_information(user_id)
        if not user_role_level['root']:
            raise MaestroException(ACCESS_DENIED, '非超级用户权限不足')
        merchant_name = cleaned_data['merchant_name']
        desc = cleaned_data['desc']
        merchant_db.update_merchant(merchant_id, merchant_name, desc)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SingleMerchantView, self).dispatch(*args, **kwargs)


class RoleView(TemplateView):
    @method_decorator(token_required)
    @method_decorator(validate_form(RoleListForm))
    def get(self, req, cleaned_data):
        merchant_id = req.merchant_id
        merchant_role = req.merchant_role
        sort_by = cleaned_data['sort_by'] or "-id"
        sort_by = sort_by.replace("supervisor_name", "supervisor_id") if "supervisor_name" in sort_by else sort_by
        query_dct = {"$order_by": sort_by}
        return merchant_handler.get_visible_roles(merchant_id, merchant_role, base_query_dct=query_dct)

    @method_decorator(token_required)
    @method_decorator(validate_form(RoleCreateForm))
    def post(self, req, cleaned_data):
        user_id = req.user_id
        merchant_id = req.merchant_id
        role_name = cleaned_data['role_name']
        desc = cleaned_data['desc']
        supervisor_id = cleaned_data['supervisor_id']
        perm = cleaned_data['perm']
        check_user_vcode(req, user_id)
        user_role_level = merchant_handler.get_user_roles_information(user_id)
        if user_role_level.get(merchant_id, {}).get('role_level') not in [RoleLevel.ROOT.value,
                                                                          RoleLevel.MANAGER.value]:
            raise MaestroException(ACCESS_DENIED)
        role_db.create_role(role_name, desc, merchant_id, supervisor_id, perm)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(RoleView, self).dispatch(*args, **kwargs)


class SingleRoleView(TemplateView):
    @method_decorator(token_required)
    def get(self, req, role_id):
        role_id = int(role_id)
        role = role_db.get_role(role_id)
        return model_to_dict(role) if role else {}

    @method_decorator(token_required)
    @method_decorator(validate_form(RoleCreateForm))
    def post(self, req, role_id, cleaned_data):
        role_id = int(role_id)
        user_id = req.user_id
        merchant_id = req.merchant_id
        role_name = cleaned_data['role_name']
        desc = cleaned_data['desc']
        supervisor_id = cleaned_data['supervisor_id']
        perm = cleaned_data['perm']
        check_user_vcode(req, user_id)
        user_role_level = merchant_handler.get_user_roles_information(user_id)
        if user_role_level.get(merchant_id, {}).get('role_level') not in [RoleLevel.ROOT.value,
                                                                          RoleLevel.MANAGER.value]:
            raise MaestroException(ACCESS_DENIED)
        role_db.update_role(merchant_id, user_role_level, role_id, role_name, desc, supervisor_id, perm)
        return {}

    @method_decorator(token_required)
    def delete(self, req, role_id):
        role_id = int(role_id)
        user_id = req.user_id
        merchant_id = req.merchant_id
        check_user_vcode(req, user_id)
        user_role_level = merchant_handler.get_user_roles_information(user_id)
        if user_role_level.get(merchant_id, {}).get('role_level') not in [RoleLevel.ROOT.value,
                                                                          RoleLevel.MANAGER.value]:
            raise MaestroException(ACCESS_DENIED)
        role_db.delete_role(merchant_id, user_role_level, role_id)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SingleRoleView, self).dispatch(*args, **kwargs)


@require_GET
@response_wrapper
def get_create_role_preset(req):
    merchant_id = req.merchant_id
    is_root = req.is_root
    merchant_role = req.merchant_role
    if is_root:
        supervisor_list = merchant_handler.get_supervisor_list(merchant_id)
    else:
        supervisor_list = [dict(key=merchant_role['id'], value=merchant_role['role_name'])]
    return dict(perm_list=permission_handler.get_permission_options(merchant_id), supervisor_list=supervisor_list)
